﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Timers;



namespace Wcf_assassins
{
    public class ServiceAssassin : IServiceAssassin
    {
        public Int32 idtuer;
        private projetAssassinEntities database = new projetAssassinEntities();
        private System.Timers.Timer timer1;
        public Int32 timestamp()
        {
            TimeSpan _TimeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
            return (Int32)_TimeSpan.TotalSeconds;
        }

        public Boolean enregisterDonnees(String idUtilisateur, String latitude, String longitude)
        {
            try
            {
                Int32 _idUtilisateur = Int32.Parse(idUtilisateur);
                double _latitude = double.Parse(latitude);
                double _longitude = double.Parse(longitude);

                if (_idUtilisateur > 0 && _latitude > 0 && _longitude > 0)
                {

                    utilisateur u = (from e in database.utilisateur
                                     where e.id == _idUtilisateur
                                     select e).First();
                    u.latitude = _latitude;
                    u.longitude = _longitude;
                    database.SaveChanges();
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch
            {
                return false;
            }

        }

        public Boolean inscrireUtilisateur(String pseudo, String motDePasse, String email)
        {
            try
            {
                String mail = email.Replace(',', '.');
                utilisateur u = new utilisateur();

                u.pseudo = pseudo;
                u.motdepasse = motDePasse;
                u.mail = email;
                u.fk_niveau = 1;
                u.fk_objet = getobjet();
                u.latitude = 0;
                u.longitude = 0;
                u.nombremort = 0;
                u.nombretue = 0;
                u.statut = 0;
                database.AddToutilisateur(u);
                database.SaveChanges();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public int authentifierUtilisateur(String pseudo, String motDePasse)
        {
            try
            {
                utilisateur u = (from e in database.utilisateur
                                 where e.pseudo == pseudo
                                 select e).First();
                if (motDePasse == u.motdepasse)
                {
                    return u.id;
                }
                else
                {
                    return -1;
                }
            }
            catch
            {
                return -1;
            }
        }

        public List<DC_Utilisateur> utilisateursEnvironnants(String idUtilisateur)
        {
            /*try
            {*/
                double distance;
                List<DC_Utilisateur> listDcUser = new List<DC_Utilisateur>();
                Int32 _idUtilisateur = Int32.Parse(idUtilisateur);
                DC_Utilisateur user;

                if (int.Parse(idUtilisateur) > 0)
                {
                    utilisateur userPlayer = (from e in database.utilisateur
                                              where e.id == _idUtilisateur
                                              select e).First();


                    List<utilisateur> userslist = (from e in database.utilisateur
                                                   where e.statut == 0
                                                   select e).ToList();
                    foreach (utilisateur users in userslist)
                    {
                        distance = GpsHelper.EarthDistanceCalc(System.Convert.ToDouble(userPlayer.longitude), System.Convert.ToDouble(userPlayer.latitude), System.Convert.ToDouble(users.longitude), System.Convert.ToDouble(users.latitude));
                        if (distance <= userPlayer.niveau.diametreperception && users.id != _idUtilisateur)
                        {
                            user = new DC_Utilisateur(users);

                            tuer tuera = (from e in database.tuer
                                        where e.id_tue == users.id
                                               && e.id_tueur == userPlayer.id
                                               //&& e.debut_chrono >= timestamp
                                               orderby e.id descending
                                                select e).FirstOrDefault();
                            if (tuera == null)
                            {
                                user.typejoueur = 3;
                            }
                            else
                            {
                                user.typejoueur = 1;
                            }

                            Int32 tmpTimestampKill = (Int32)timestamp() - (Int32)(userPlayer.niveau.tempschrono);

                            var tuerContrer = (from e in database.tuer
                                        where e.id_tue == users.id
                                               && e.id_tueur == userPlayer.id
                                               && e.debut_chrono >= tmpTimestampKill
                                        select e);

                            if (tuerContrer.Count() >= 1)
                            {
                                user.typejoueur = 2;
                            }
                           
                            listDcUser.Add(user);
                        }
                    }
                }
                return listDcUser;
            /*}
            catch
            {
                return null;
            }*/
        }

        public DC_Utilisateur getUtilisateur(String idUtilisateur)
        {
            try
            {
                Int32 _iduser = Int32.Parse(idUtilisateur);

                utilisateur user = (from e in database.utilisateur
                                    where e.id == _iduser
                                    select e).First();

                return new DC_Utilisateur(user);
            }
            catch
            {
                return null;
            }
        }

        public int chrono(String joueur, String cible)
        {
            try
            {
                Int32 _joueur = Int32.Parse(joueur);
                Int32 _cible = Int32.Parse(cible);
                //Int32 _timestamp = timestamp();

                utilisateur j = (from e in database.utilisateur
                                 where e.id == _joueur
                                 select e).First();
                utilisateur c = (from e in database.utilisateur
                                 where e.id == _cible
                                 select e).First();
                niveau n = (from e in database.niveau
                            where e.id == j.fk_niveau
                            select e).First();
                tuer t = new tuer();
                t.id_tueur = _joueur;
                t.id_tue = _cible;
                t.debut_chrono = timestamp();
                database.AddTotuer(t);
                database.SaveChanges();
                
                timer1 = new System.Timers.Timer();
                timer1.Interval = (double)n.tempschrono;
                timer1.Interval = 10000;
                
                idtuer = t.id;
                //timer1.Elapsed += new ElapsedEventHandler(timer1_fin);
                timer1.Start();
                return Convert.ToInt32(n.tempschrono);
            }
            catch (Exception ex)
            {
                                return -1;
            }
        }

        //Appelé à la fin du chrono d'assassinat.
        //A ce moment on vérifie qu'il est pas déjà tué (car espionnage) et on supprime de la table tuer + actions correspondantes
        //private void timer1_fin(object sender, EventArgs e)
        //{
        //    try
        //    {
        //        tuer t = (from ze in database.tuer
        //                  where ze.id == idtuer
        //                  select ze).First();
        //        assassinat(t.id_tueur.ToString(), t.id_tueur.ToString());

        //    }
        //    catch (Exception ex)
        //    {
        //        ;
        //    }


        //}
        
        public int assassinat(String joueur, String cible)
        {
            try
            {
                Int32 _joueur = Int32.Parse(joueur);
                Int32 _cible = Int32.Parse(cible);
                Int32 _timestamp = timestamp();

                utilisateur j = (from e in database.utilisateur
                                 where e.id == _joueur
                                 select e).First();
                utilisateur c = (from e in database.utilisateur
                                 where e.id == _cible
                                 select e).First();
                niveau n = (from e in database.niveau
                            where e.id == j.fk_niveau
                            select e).First();
                niveau nc = (from e in database.niveau
                             where e.id == c.fk_niveau
                             select e).First();
                //tuer t = (from e in database.tuer
                //          where e.id_tueur == _joueur && e.id_tue == _cible
                //          select e).First();
                c.nombremort = c.nombremort + 1;
                j.nombretue = j.nombretue + 1;
                c.statut = _timestamp;
                database.SaveChanges();
                if (j.nombretue >= n.nombrecible && j.fk_niveau < 5)
                {
                    j.fk_niveau = j.fk_niveau + 1;
                    database.SaveChanges();
                }
                appartenir_objet ao = new appartenir_objet();
                ao.id_utilisateur = j.id;
                ao.id_objet = c.fk_objet;
                database.AddToappartenir_objet(ao);
                database.SaveChanges();
                //database.DeleteObject(t);
                database.SaveChanges();
                return int.Parse(nc.tempsmort.ToString());
            }
            catch (Exception ex)
            {
                return -1;
            }
        }

        public int espionnage(String joueur, String cible, String espion)
        {
            try
            {
                Int32 _joueur = Int32.Parse(joueur);
                Int32 _cible = Int32.Parse(cible);
                Int32 _espion = Int32.Parse(espion);
                Int32 _timestamp = timestamp();

                tuer t = (from e in database.tuer
                          where e.id_tueur == _joueur && e.id_tue == _cible
                          select e).First();
                if (t != null)
                {
                    utilisateur j = (from e in database.utilisateur
                                     where e.id == _joueur
                                     select e).First();
                    utilisateur esp = (from e in database.utilisateur
                                       where e.id == _espion
                                       select e).First();
                    niveau n = (from e in database.niveau
                                where e.id == j.fk_niveau + 1
                                select e).First();
                    niveau nc = (from e in database.niveau
                                 where e.id == j.fk_niveau
                                 select e).First();
                    j.nombremort = j.nombremort + 1;
                    esp.nombretue = esp.nombretue + 1;
                    j.statut = _timestamp;
                    if (esp.nombretue >= n.nombrecible && j.fk_niveau < 5)
                    {
                        esp.fk_niveau = j.fk_niveau + 1;
                    }
                    appartenir_objet ao = new appartenir_objet();
                    ao.id_utilisateur = esp.id;
                    ao.id_objet = j.fk_objet;
                    database.AddToappartenir_objet(ao);
                    database.DeleteObject(t);
                    database.SaveChanges();
                    return int.Parse(nc.tempsmort.ToString());
                }
                return 0;
            }
            catch (Exception ex)
            {
                return -1;
            }
        }

        public int getcible(String joueur)
        {
            try
            {
                Int32 _joueur = Int32.Parse(joueur);
                List<DC_Utilisateur> list = new List<DC_Utilisateur>();
                list = utilisateursEnvironnants(_joueur.ToString());
                Random randNum = new Random();
                int rnded = randNum.Next(list.Count);
                tuer ao = new tuer();
                ao.id_tueur = _joueur;
                ao.id_tue = list[rnded].id;
                database.AddTotuer(ao);
                database.SaveChanges();
                return list[rnded].id;
                            }
            catch (Exception ex)
            {
                return -1;
            }
        }

        public int getobjet()
        {
            try
            {
                List<objet> userslist = (from e in database.objet select e).ToList();
                Random randNum = new Random();
                int rnded = randNum.Next(userslist.Count);
                return userslist[rnded].id;
            }
            catch
            {
                return -1;
            }
        }

        public List<DC_Utilisateur> topusers()
        {
            try
            {
                List<utilisateur> llist = (from e in database.utilisateur
                                           orderby e.nombretue descending
                                           select e).Take(10).ToList();
                List<DC_Utilisateur> userslist = new List<DC_Utilisateur>();
                foreach (utilisateur item in llist)
                {
                    DC_Utilisateur dc = new DC_Utilisateur(item);
                    userslist.Add(dc);
                }
                return userslist;
            }
            catch
            {
                return null;
            }
        }

        public List<DC_Objet> getObjets(String idUtilisateur)
        {
            try
            {
                Int32 _iduser = Int32.Parse(idUtilisateur);

                List<appartenir_objet> obj = (from e in database.appartenir_objet
                                              where e.id_utilisateur == _iduser
                                              select e).ToList();
                List<DC_Objet> dco = new List<DC_Objet>();

                foreach (appartenir_objet ao in obj)
                {
                    dco.Add(new DC_Objet(ao));
                }
                return dco;

            }
            catch
            {
                return null;
            }
        }

        public int resurrection(String joueur)
        {
            try
            {
                Int32 _joueur = Int32.Parse(joueur);
                Int32 _timestamp = timestamp();

                utilisateur j = (from e in database.utilisateur
                                 where e.id == _joueur
                                 select e).First();
                niveau n = (from e in database.niveau
                            where e.id == j.fk_niveau
                            select e).First();
                if ((_timestamp - (j.statut + n.tempsmort) > 0))
                {
                    j.statut = 0;
                    j.fk_objet = getobjet();
                    database.SaveChanges();
                    return getcible(joueur);
                }
                else
                {
                    return -10;
                }
            }
            catch
            {
                return -1;
            }
        }
    }
}
